package the.broccoli.uc.controller;

import io.swagger.annotations.ApiParam;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.wisteria.framework.web.APIResult;
import org.wisteria.framework.web.QueryResult;
import org.wisteria.framework.web.mvc.constant.WebConsts;
import the.broccoli.ac.service.IResService;
import the.broccoli.auth.UserContext;
import the.broccoli.uc.dto.RoleCondition;
import the.broccoli.uc.entity.Role;
import the.broccoli.uc.entity.RoleRes;
import the.broccoli.uc.entity.User;
import the.broccoli.uc.entity.UserRole;
import the.broccoli.uc.service.*;
import the.broccoli.uc.vo.RoleResSelect;
import the.broccoli.uc.vo.RoleUserSelect;

import javax.annotation.Resource;
import java.util.*;

/**
 * 角色控制器
 *
 * @author lei.liu
 * @since 2020-04-01 18:20:22
 */
@RestController
@RequestMapping("/uc/role")
public class RoleController {

    @Resource
    private IRoleService roleService;

    @Resource
    private IRoleResService roleResService;

    @Resource
    private IUserRoleService userRoleService;

    @Resource
    private IResService resService;

    @Resource
    private ITenantAppService tenantAppService;

    @Resource
    private IUserService userService;

    @PostMapping("/add")
    public APIResult add(
            @ApiParam(name = "parentId", value = "父级ID", required = true)
            @RequestParam(name = "parentId", required = true) String parentId,
            @ApiParam(name = "roleName", value = "角色名称", required = true)
            @RequestParam(name = "roleName", required = true) String roleName,
            @ApiParam(name = "roleCode", value = "角色编号", required = false)
            @RequestParam(name = "roleCode", required = false) String roleCode,
            @ApiParam(name = "remark", value = "备注", required = false)
            @RequestParam(name = "remark", required = false) String remark,
            @ApiParam(name = "constant", value = "代码", required = false)
            @RequestParam(name = "constant", required = false) String constant
    ) {
        Role entity = new Role();
        entity.setParentId(parentId);
        entity.setRoleName(roleName);
        entity.setRoleCode(roleCode);
        entity.setRemark(remark);
        entity.setConstant(constant);
        entity.setCreatedId(UserContext.userId());
        entity.setCreatedName(UserContext.userName());
        entity.setCreatedTime(new Date());
        entity.setTenantId(UserContext.tenantId());
        roleService.save(entity);
        return APIResult.success();
    }

    @PostMapping("/remove")
    public APIResult remove(@RequestParam(value = "ids", required = true) List<String> ids) {
        roleService.removeByIds(ids, UserContext.userId(), UserContext.userName());
        return APIResult.success();
    }

    @PostMapping("/modify")
    public APIResult modify(
            @ApiParam(name = "roleId", value = "角色ID", required = true)
            @RequestParam(name = "roleId", required = true) String roleId,
            @ApiParam(name = "roleName", value = "角色名称", required = true)
            @RequestParam(name = "roleName", required = true) String roleName,
            @ApiParam(name = "roleCode", value = "角色编号", required = false)
            @RequestParam(name = "roleCode", required = false) String roleCode,
            @ApiParam(name = "remark", value = "备注", required = false)
            @RequestParam(name = "remark", required = false) String remark
    ) {
        Role entity = new Role();
        entity.setRoleId(roleId);
        entity.setRoleName(roleName);
        entity.setRoleCode(roleCode);
        entity.setRemark(remark);
        entity.setModifiedId(UserContext.userId());
        entity.setModifiedName(UserContext.userName());
        entity.setModifiedTime(new Date());
        roleService.updateById(entity);
        return APIResult.success();
    }

    @GetMapping("/{roleId}")
    public APIResult get(@PathVariable(value = "roleId") String roleId) {
        return APIResult.success(roleService.getById(roleId));
    }

    @GetMapping("/page")
    public APIResult<QueryResult> page(
            @ApiParam(name = "roleName", value = "角色名称", required = false)
            @RequestParam(name = "roleName", required = false) String roleName,
            @ApiParam(name = "roleCode", value = "角色编号", required = false)
            @RequestParam(name = "roleCode", required = false) String roleCode,
            @ApiParam(name = "keyword", value = "关键字", required = false)
            @RequestParam(value = "keyword", required = false) String keyword,
            @ApiParam(name = "orderBy", value = "排序字段", required = false)
            @RequestParam(value = "orderBy", required = false) String orderBy,
            @ApiParam(name = "pageNum", value = "页码", required = false, defaultValue = "1")
            @RequestParam(value = "pageNum", required = false) Integer pageNum,
            @ApiParam(name = "pageNum", value = "每页大小", required = false, defaultValue = "20")
            @RequestParam(value = "pageSize", required = false) Integer pageSize
    ) {
        RoleCondition vo = new RoleCondition();
        vo.setTenantId(UserContext.tenantId());
        vo.setRoleName(roleName);
        vo.setRoleCode(roleCode);
        vo.setKeyword(keyword);
        vo.setOrderBy(orderBy);
        return APIResult.success(roleService.pageList(vo, pageNum, pageSize));
    }



    @GetMapping("/tree/list")
    public APIResult listTree() {
        Set<Role> roleTreeList = new HashSet<>();

        List<String> roleIdList = userRoleService.getRoleIdList(UserContext.userId());
        if (!CollectionUtils.isEmpty(roleIdList)) {

            RoleCondition condition = new RoleCondition();
            condition.setTenantId(UserContext.tenantId());
            condition.setRoleParentIdList(roleIdList);
            List<Role> roleList = roleService.listByCondition(condition);

            if (!CollectionUtils.isEmpty(roleList)) {
//                for (Role role : roleList) {
//                    if ("".equals(role.getParentId()) || WebConsts.ROOT.equalsIgnoreCase(role.getParentId())) {
//                        role.setParentId("0");
//                    }
//                    roleTreeList.add(role);
//                }
                for (String roleId : roleIdList) {
                    recursive(roleId, roleList, roleTreeList);

                    for (Role role : roleList) {
                        if (roleId.equals(role.getRoleId())) {
                            role.setParentId("");
                            roleTreeList.add(role);
                        }
                    }
                }
            }
        }

        return APIResult.success(roleTreeList);
    }

    private void recursive(String roleId, List<Role> roleList, Set<Role> roleTreeList) {
        for (Role role : roleList) {
            if (roleId.equals(role.getParentId())) {
                roleTreeList.add(role);
                recursive(role.getRoleId(), roleList, roleTreeList);
            }
        }
    }

    @GetMapping("/{roleId}/res/tree")
    public APIResult tree(
            @ApiParam(name = "roleId", value = "角色ID", required = true)
            @PathVariable(name = "roleId") String roleId) {
        RoleResSelect data = new RoleResSelect();
        Role currRole = roleService.getById(roleId);
        if (currRole != null) {
            // 已关联的资源ID
            data.setResIdList(roleResService.getResIdList(currRole.getRoleId()));

            // 所有可关联资源
            String parentRoleId = currRole.getParentId();
            if (roleService.isAdmin(parentRoleId)) {
                // 租户关联的应用资源
                data.setResTree(resService.getAppResTree(tenantAppService.getAppIdList(UserContext.tenantId()), null));
            } else {
                // 角色关联的资源
                data.setResTree(roleResService.getResTree(parentRoleId));
            }
        }
        return APIResult.success(data);
    }

    @PostMapping("/res/add")
    public APIResult<List<String>> addRoleRes(
            @ApiParam(name = "roleId", value = "角色ID", required = true)
            @RequestParam(name = "roleId", required = true) String roleId,
            @ApiParam(name = "resIdList", value = "资源ID", required = true)
            @RequestParam(name = "resIdList", required = true) List<String> resIdList
    ) {
        roleResService.save(roleId, resIdList, UserContext.userId(), UserContext.userName());
        return APIResult.success();
    }

    @PostMapping("/res/append")
    public APIResult<List<String>> addRoleResSingle(
            @ApiParam(name = "roleId", value = "角色ID", required = true)
            @RequestParam(name = "roleId", required = true) String roleId,
            @ApiParam(name = "resId", value = "资源ID", required = true)
            @RequestParam(name = "resId", required = true) String resId
    ) {
        RoleRes entity = new RoleRes();
        entity.setRoleId(roleId);
        entity.setResId(resId);
        entity.setCreatedId(UserContext.userId());
        entity.setCreatedName(UserContext.userName());
        entity.setCreatedTime(new Date());
        roleResService.save(entity);
        return APIResult.success();
    }

    @PostMapping("/user/add")
    public APIResult<List<String>> addRoleUser(
            @ApiParam(name = "roleId", value = "角色ID", required = true)
            @RequestParam(name = "roleId", required = true) String roleId,
            @ApiParam(name = "userIdList", value = "用户ID", required = true)
            @RequestParam(name = "userIdList", required = true) List<String> userIdList
    ) {
        userRoleService.save(userIdList, roleId, UserContext.userId(), UserContext.userName());
        return APIResult.success();
    }

    @GetMapping("/user/list")
    public APIResult listRoleUser(
            @ApiParam(name = "roleId", value = "角色ID", required = true)
            @RequestParam(name = "roleId", required = true) String roleId
    ) {
        List<RoleUserSelect> data = null;
        List<UserRole> list = userRoleService.listByRoleId(roleId);
        if (!CollectionUtils.isEmpty(list)) {
            data = new ArrayList<>();
            RoleUserSelect vo = null;
            for (UserRole entity : list) {
                User user = userService.getById(entity.getUserId());
                if (user.getIsDeleted() == null || user.getIsDeleted().intValue() != 0) {
                    continue;
                }

                vo = new RoleUserSelect();
                vo.setUserId(entity.getUserId());

                vo.setUserName(user == null ? null : user.getUserName());
                data.add(vo);
            }
        }
        return APIResult.success(data);
    }

}